mysql 如何做到crash后无损恢复数据的

ps

  真实的流程没有我说的那么简单,下面的是最基本的情况。

预备知识

  • redolog
  • binlog
  • WAL机制

redolog简介

  redolog是个循环日志,其大小固定为4g,存在2个指针来定位其是否已经满了。一个指针是当前写,一个指针是当前checkpoint,其2个指针的顺时针空间就是可写的空间。

  这个redolog就是完成mysql突然宕机后,如何无损恢复数据的。

binlog简介

  这个是mysql自身的日志,叫做归档日志。和redolog大致3个不同点。

  • 其为mysql自带的,redolog是innodb里面的。
  • redolog是物理日志,binlog是逻辑日志。
  • redolog是循环日志,binlog是增量日志。

  这里不对其过多介绍,下一篇文章关于主从的详细介绍,主从就是通过binlog完成的。

WAL机制简介

  MySQL里经常说到的 WAL 技术,意思就是数据入库前先写进去日志,再写磁盘里面。

  这里采用的是数据安全性最高的双1策略。

  其数据更新顺序也保持着其顺序。

  下面我来简单介绍下。

  1.当要更新id=2这一行数据时,先通过这个表的索引,查询到这行记录所在的数据页。然后判断这个数据页是否在buffer pool(这个是内存)。

  2.如果不在内存则需要读到内存(其实也可以不用读入内存,当要更新的这行数据没有唯一索引时,mysql为了提高效率,采用了change buffer(别看有个buffer,但是人家也是持久化到磁盘的)这个东西,将对这行修改的动作记录到change buffer里面,就不用读到内存了)。

  3.在buffer pool 内存上修改这行数据(仅仅只是在内存上修改了这行数据,并没有持久化到磁盘里面)。

  4.将上面的操作,写入到redolog里面,且将这个操作状态设置为prepare状态,首先写到redologbuffer里面(为了提高效率,mysql做了组提交这个优化,这里不扩展),等到这个事务提交后,redologbuffer然后再写入到文件系统的page cache里面,然后立马调用fsync,将其刷到磁盘。

  5.然后写入到binlog里面,先写到binlog cache里面,然后写入page cache,然后调用fsync,写入磁盘。

  6.redolog继续写一次,将其状态设置为commit状态。
  如此就算完成了一个更新操作。

mysql 如何做到crash后,数据不丢失的

  前面说了数据更新操作。
  当前buffer pool里面存在大量脏页(就是一些数据页,只在内存里面修改了,没有刷新到磁盘),当系统宕机了,内存里面的数据全部丢失了怎么办?
  方法如下:我们需要redolog来完成灾难备份,check point到writ pos这块空间记录的所有的操作步骤派上用场了,根据这些redolog记录从磁盘里面读取所有相关的数据页。然后按照redolog上的操作恢复数据即可,那么我们发现存再内存的数据全部恢复了。